package com.sea.base.utils

import android.annotation.SuppressLint
import android.app.Activity
import android.app.Application
import androidx.annotation.MainThread
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.sea.base.ext.global.registerActivityLifecycleCallbacks
import com.sea.base.ext.global.singleApplication
import com.sea.base.ext.obs.observeCustom
import com.sea.base.ext.obs.smartPost
import java.util.*

/**
 * activity管理
 *
 * 注意：请在super.onCreate之后进行使用，原因见[Application.ActivityLifecycleCallbacks.onActivityCreated]
 * 解决方案是api>=29时改为onActivityPreCreated，目前无解
 */
@Suppress("unused")
@SuppressLint("StaticFieldLeak") //自身有管理，不会泄露
object ActivityStackManager {
    private val activityStack = LinkedList<Activity>()
    private var waitStopCount = 0
    private var isInit = false

    /**
     * app可见性变更，true：可见，false：不可见（后台）
     */
    private val _appVisibleChangedObserver = MutableLiveData<Boolean>()
    val appVisibleChangedObserver: LiveData<Boolean> get() = _appVisibleChangedObserver

    /**
     * 必须由application初始化时调用
     */
    @JvmStatic
    fun init() {
        if (isInit) {
            return
        }
        isInit = true
        singleApplication.registerActivityLifecycleCallbacks(
            onCreated = { it, _ -> activityStack.add(it) },
            onStarted = {
                waitStopCount++
                if (isAppVisible()) {
                    _appVisibleChangedObserver.smartPost(true)
                }
            },
            onStopped = {
                waitStopCount--
                if (!isAppVisible()) {
                    _appVisibleChangedObserver.smartPost(false)
                }
            },
            onDestroyed = { activityStack.remove(it) }
        )
    }

    private fun removeFinishedActivity() {
        activityStack.removeIf { it.isFinishing }
    }

    /**
     * 获取当前Activity的前一个Activity
     */
    @MainThread
    @JvmStatic
    fun preActivity(): Activity? {
        removeFinishedActivity()
        return activityStack.getOrNull(activityStack.lastIndex - 1)
    }

    /**
     * 结束指定的Activity
     */
    @MainThread
    @JvmStatic
    fun finishActivity(activity: Activity? = getCurrentActivity()) {
        activity?.let {
            activityStack.remove(it)
            it.finish()
        }
    }

    /**
     * @param firstOnly 是否只finish第一个匹配的cls（cls可能会命中多个）
     */
    @MainThread
    @JvmStatic
    fun finishActivity(cls: Class<*>, firstOnly: Boolean = false) {
        finishActivity(cls.name, firstOnly)
    }

    @MainThread
    @JvmStatic
    fun finishActivity(clsName: String, firstOnly: Boolean = false) {
        removeFinishedActivity()
        activityStack.descendingIterator().forEach {
            if (it.javaClass.name == clsName) {
                finishActivity(it)
                if (firstOnly) {
                    return
                }
            }
        }
    }

    /**
     * 关掉全部Activity
     * @param ignoreActivity 此Activity不finish
     */
    @MainThread
    @JvmStatic
    fun finishAllActivity(ignoreActivity: Activity? = null) {
        if (activityStack.isEmpty()) {
            return
        }
        //创建副本，防止循环触发finishAllActivity
        val list = activityStack.toList()
        activityStack.clear()

        list.forEach {
            if (ignoreActivity != it) {
                it.finish()
            }
        }

        //添加保留的Activity
        if (ignoreActivity?.isFinishing == false) {
            activityStack.add(ignoreActivity)
        }
    }

    /**
     * 回退到指定的activity
     */
    @MainThread
    @JvmStatic
    fun returnToActivity(cls: Class<*>) {
        removeFinishedActivity()
        while ((activityStack.lastOrNull() ?: return).javaClass != cls) {
            finishActivity(activityStack.lastOrNull())
        }
    }

    /**
     * 指定activity是否存在
     */
    @MainThread
    @JvmStatic
    fun isOpenedActivity(cls: Class<*>): Boolean {
        removeFinishedActivity()
        activityStack.forEach {
            if (cls == it.javaClass) {
                return true
            }
        }
        return false
    }

    /**
     * 获取当前Activity（最后一个没finish的Activity）
     */
    @MainThread
    @JvmStatic
    fun getCurrentActivity(): Activity? {
        removeFinishedActivity()
        return activityStack.lastOrNull()
    }

    /**
     * app是否可见，true：可见，false：后台
     */
    @MainThread
    @JvmStatic
    fun isAppVisible() = waitStopCount > 0

    /**
     * 获取当前临时栈信息
     */
    @MainThread
    @JvmStatic
    fun getNowActivityStack(): List<Activity> {
        removeFinishedActivity()
        return activityStack
    }

    /**
     * 是否有homeActivity
     */
    @MainThread
    @JvmStatic
    fun hasHomeActivity(): Boolean {
        activityStack.forEach {
            if (it.javaClass.simpleName == AppUtil.instance.homeActivitySimpleName) {
                return true
            }
        }
        return false
    }

    /**
     * 当app可见时回调
     */
    inline fun doOnAppVisible(crossinline call: (Activity) -> Unit) {
        val activity = getCurrentActivity()
        if (isAppVisible() && activity != null) {
            call.invoke(activity)
            return
        }
        appVisibleChangedObserver.observeCustom(null, obsOnce = true, obsNext = true) {
            val activity = getCurrentActivity()
            if (it && activity != null) {
                call.invoke(activity)
            }
        }
    }

    /**
     * 当app隐藏时回调
     * 注意：不要在activity、fragment里直接调用，会引起内存泄漏
     */
    inline fun doOnAppHide(crossinline call: () -> Unit) {
        if (!isAppVisible()) {
            call.invoke()
            return
        }
        appVisibleChangedObserver.observeCustom(null, obsOnce = true, obsNext = true) {
            if (!it) {
                call.invoke()
            }
        }
    }
}